﻿using System.Diagnostics;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using DesktopToyWpf.Services;
using DesktopToyWpf.ViewModels;
using DesktopToyWpf.Views;

namespace DesktopToyWpf;

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow
{
    // todo：后续把时间折线图的起始时间定位早上8点
    
    public MainWindow()
    {
        InitializeComponent();
        DataContext = Global.MainViewModel;

        if (Global.Storage.WindowLocation == null)
        {
            WindowStartupLocation = WindowStartupLocation.CenterScreen;
        }
        else
        {
            Width = Global.Storage.WindowWidth;
            
            if (Global.Storage.WindowLocation.Value.X < 0d && Global.Storage.WindowLocation.Value.Y < 0d)
            {
                WindowStartupLocation = WindowStartupLocation.CenterScreen;
            }
            else
            {
                WindowStartupLocation = WindowStartupLocation.Manual;
                Left = Global.Storage.WindowLocation.Value.X;
                Top = Global.Storage.WindowLocation.Value.Y;
            }
        }
        
        MainControl.WeatherControl.MouseLeftButtonDown += WeatherControl_OnMouseLeftButtonDown;
    }

    private static MainService MainService => Global.MainService;
    private static MainViewModel ViewModel => Global.MainViewModel;
    private DispatcherTimer SecondTickTimer;
    private DispatcherTimer HourTickTimer;

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        Init();
    }

    private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
    {
        ResizeBorderWindow.Setup(this, ResizeDirection.Left, 12d);
        ResizeBorderWindow.Setup(this, ResizeDirection.Right, 12d);
    }

    private void MainWindow_OnClosed(object? sender, EventArgs e)
    {
        Global.OnClosed();
    }

    private void MainWindow_OnDpiChanged(object sender, DpiChangedEventArgs e)
    {
        SizeToContent = SizeToContent.Manual;
        SizeToContent = SizeToContent.Height;
        Global.Storage.Dpi = VisualTreeHelper.GetDpi(this).DpiScaleX;
    }

    private void Init()
    {
        // 时钟对齐，这样秒针尽量跟系统同步
        var delay = 1000 - DateTime.Now.Millisecond;
        if (delay >= 100)
        {
            Thread.Sleep(delay);
        }

        SecondTickTimer = new DispatcherTimer(DispatcherPriority.Normal, Dispatcher);
        SecondTickTimer.Tick += OnSecondTick;
        SecondTickTimer.Interval = new TimeSpan(0, 0, 1);
        SecondTickTimer.Start();

        HourTickTimer = new DispatcherTimer(DispatcherPriority.Normal, Dispatcher);
        HourTickTimer.Tick += OnHourTick;
        HourTickTimer.Interval = new TimeSpan(1, 0, 0);
        HourTickTimer.Start();

        UpdateWeatherAsync(true);
    }

    private const int UPDATE_DEVICE_INFO_INTERVAL = 5;
    private int UpdateDeviceInfoRemain = 0;
    private DateTime? LastTickTime;

    private void OnSecondTick(object? sender, EventArgs e)
    {
        var now = DateTime.Now;
        if (LastTickTime != null)
        { 
            // 判断是否跨天了
            if (now.Day != LastTickTime.Value.Day || 
                now.Month != LastTickTime.Value.Month ||
                now.Year != LastTickTime.Value.Year)
            {
                Global.InitViewModel();
                Global.SaveStorage();
                DataContext = Global.MainViewModel;
                UpdateDeviceInfo();
                UpdateWeather();
            }
        }
        
        LastTickTime = now;
        ViewModel.Now = DateTime.Now;

        UpdateDeviceInfoRemain--;
        if (UpdateDeviceInfoRemain <= 0)
        {
            UpdateDeviceInfoRemain = UPDATE_DEVICE_INFO_INTERVAL;
            UpdateDeviceInfo();
        }
    }

    private void UpdateDeviceInfo()
    {
        ViewModel.CpuTemperature = MainService.GetCpuTemperature();
        ViewModel.GpuTemperature = MainService.GetGpuTemperature();
        ViewModel.StorageTemperature = MainService.GetStorageTemperature();
    }

    private void OnHourTick(object? sender, EventArgs e)
    {
        UpdateWeatherAsync(false);
    }
    
    private void UpdateWeatherAsync(bool isFirst)
    {
        if (isFirst)
        {
            MainControl.WeatherControl.Visibility = Visibility.Hidden;
        }

        Task.Run(UpdateWeather);
    }

    private void UpdateWeather()
    {
        Debug.WriteLine("更新天气...");
        var weather = MainService.GetCurrentWeather();

        Dispatcher.Invoke(() =>
        {
            if (weather == null)
            {
                MainControl.WeatherControl.Visibility = Visibility.Hidden;
                return;
            }

            ViewModel.Weather = weather.Weather;
            ViewModel.Temperature = weather.Temperature;
            ViewModel.WindDirection = weather.WindDirection;
            ViewModel.WindPower = weather.WindPower;
            ViewModel.Humidity = weather.Humidity;
            ViewModel.WeatherTips = $"上次更新时间：{DateTime.Now:yyyy/MM/dd HH:mm:ss}\r\n天气报告时间：{weather.ReportTime:yyyy/MM/dd HH:mm:ss}\r\n（鼠标左键点击更新天气）";

            MainControl.WeatherControl.Visibility = Visibility.Visible;
            Debug.WriteLine("更新天气...完毕");
        });
    }
    
    private async void WeatherControl_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        try
        {
            MainControl.WeatherControl.Visibility = Visibility.Hidden;
            await Task.Delay(500);
            UpdateWeather();
        }
        catch (Exception)
        {
            MainControl.WeatherControl.Visibility = Visibility.Visible;
            ViewModel.WeatherTips = "更细天气失败，请重试。\r\n（鼠标左键点击更新天气）";
        }
    }

    private void MainWindow_OnLocationChanged(object? sender, EventArgs e)
    {
        if (IsLoaded && WindowState != WindowState.Minimized)
        {
            var point = PointToScreen(new Point(0, 0));
            if (point is { X: >= 0, Y: >= 0 })
            {
                Global.Storage.WindowLocation = point;
            }
        }
    }

    private void MainWindow_OnSizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (IsLoaded)
        {
            Global.Storage.WindowWidth = Width;
        }
    }
}